package com.tencreat.api.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tencreat.common.api.MsgApi;
import com.tencreat.common.core.HttpResult;
import com.tencreat.common.core.enums.ImMessageType;
import com.tencreat.common.core.enums.ImSessionType;
import com.tencreat.common.core.enums.TrueFalseType;
import com.tencreat.common.core.exception.CustomException;
import com.tencreat.common.core.utils.IpUtils;
import com.tencreat.common.core.utils.JwtService;
import com.tencreat.common.core.utils.ServletUtils;
import com.tencreat.common.entity.ImMessage;
import com.tencreat.common.entity.ImUser;
import com.tencreat.common.entity.ImUserSession;
import com.tencreat.common.entity.req.*;
import com.tencreat.common.entity.vo.UserSessionVo;
import com.tencreat.common.service.ImMessageService;
import com.tencreat.common.service.ImSessionService;
import com.tencreat.common.service.ImSettingService;
import com.tencreat.common.service.ImUserSessionService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.time.LocalDateTime;

/**
 * 用户接口
 */
@RestController
@RequestMapping("/api")
public class ImApiController extends BaseController{

    @Autowired
    ImSessionService sessionService;
    @Autowired
    ImMessageService messageService;
    @Autowired
    ImUserSessionService imUserSessionService;
    @Autowired
    ImSettingService settingService ;
    @Autowired
    JwtService jwtService;
    @Autowired
    MsgApi msgApi;


    /**
     * jwt注册
     * @param request
     * @return
     */
    @PostMapping("/account/register")
    public HttpResult<String> register(HttpServletRequest request) {
        ImUser user = jwtService.getUser(request);
        if(null != user){
            userService.newUser(user);
        }else{
            return HttpResult.error("token无效，注册失败");
        }
        return HttpResult.ok();
    }

    /**
     * 账号密码登录1
     * @param param
     * @return
     */
    @PostMapping("/account/login")
    public HttpResult<String> login(@Valid @RequestBody ReqLoginParam param) {
        ImUser one = userService.lambdaQuery().eq(ImUser::getUsername, param.getUsername())
                .eq(ImUser::getPassword, param.getPassword())
                .one();
        if(null != one){
            String token = jwtService.createToken(one);
            return HttpResult.ok(token);
        }
        return HttpResult.error("用户名或密码错误!");
    }


    /**
     * 用户列表
     * @param param
     * @return
     */
    @PostMapping("/account/list")
    public HttpResult<Page<ImUser>> accountList(@RequestBody ReqUserParam param) {
        Page<ImUser> page = new Page<>(param.getPageNum(), param.getPageSize());
        page = userService.lambdaQuery()
                .select(ImUser::getUsername, ImUser::getId, ImUser::getAvatar, ImUser::getNickname)
                .like(ImUser::getUsername, param.getUsername())
                .page(page);
        return HttpResult.ok(page);
    }

    /**
     * 获取会话列表
     * @param pageParam
     * @return
     */
    @PostMapping("/session/list")
    public HttpResult<Page<UserSessionVo>> sessionList(@RequestBody ReqPageParam pageParam) {
        ImUser user = getLoginUser();
        // 更新用户客户端信息
        updateUserClient(user);

        Page<UserSessionVo> page = new Page<>(pageParam.getPageNum(), pageParam.getPageSize());
        page = sessionService.sessionList(page, user.getId());
        return HttpResult.ok(page);
    }

    /**
     * 编辑会话
     * @param editParam
     * @return
     */
    @PostMapping("/session/edit")
    public HttpResult<Boolean> sessionList(@RequestBody ReqSessionEditParam editParam) {
        ImUser user = getLoginUser();
        boolean update = imUserSessionService.lambdaUpdate().eq(ImUserSession::getSessionId, editParam.getSessionId())
                .eq(ImUserSession::getUserId, user.getId())
                .set(ImUserSession::getName, editParam.getSessionName())
                .update();
        return HttpResult.ok(update);
    }

    /**
     * 打开会话
     * @param param
     * @return
     */
    @PostMapping("/session/open")
    public HttpResult<UserSessionVo> openSession(@RequestBody ReqIdParam param) {
        ImUser loginUser = getLoginUser();
        UserSessionVo userSessionVo;
        ImUserSession one = imUserSessionService.lambdaQuery().eq(ImUserSession::getUserId, loginUser.getId())
                .eq(ImUserSession::getToId, param.getId()).one();
        if(null != one){
            one.setIsShow(TrueFalseType.TRUE);
            userSessionVo = new UserSessionVo();
            BeanUtils.copyProperties(one, userSessionVo);
        }else{
            ImUser toUser = userService.getById(param.getId());
            userSessionVo = sessionService.newSession(loginUser, toUser);
        }
        userSessionVo.setFromAvatar(loginUser.getAvatar());
        return HttpResult.ok(userSessionVo);
    }


    /**
     * 置顶会话
     * @param operateParam
     * @return
     */
    @PostMapping("/session/top")
    public HttpResult<Boolean> sessionTop(@RequestBody ReqOperateParam operateParam) {
        ImUser user = getLoginUser();
        boolean update = imUserSessionService.lambdaUpdate().eq(ImUserSession::getUserId, user.getId())
                .eq(ImUserSession::getSessionId, operateParam.getId())
                .set(ImUserSession::getIsTop, operateParam.getOperate())
                .set(ImUserSession::getTopTime, LocalDateTime.now())
                .update();
        return HttpResult.ok(update);
    }

    /**
     * 删除会话
     * @param operateParam
     * @return
     */
    @PostMapping("/session/delete")
    public HttpResult<Boolean> sessionDelete(@RequestBody ReqOperateParam operateParam) {
        ImUser user = getLoginUser();
        boolean update = imUserSessionService.lambdaUpdate().eq(ImUserSession::getUserId, user.getId())
                .eq(ImUserSession::getSessionId, operateParam.getId())
                .set(ImUserSession::getIsShow, operateParam.getOperate())
                .update();
        return HttpResult.ok(update);
    }

    /**
     * 获取聊天记录
     * @param param
     * @return
     */
    @PostMapping("/session/history")
    @Transactional
    public HttpResult<Page<ImMessage>> sessionHistory(@RequestBody ReqIdAndPageParam param) {
        ImUser loginUser = getLoginUser();
        ImUserSession userSession = imUserSessionService.lambdaQuery().eq(ImUserSession::getUserId, loginUser.getId())
                .eq(ImUserSession::getSessionId, param.getId())
                .one();
        if(null == userSession){
            throw new CustomException("会话错误！");
        }

        QueryWrapper<ImMessage> wrapper = new QueryWrapper<>();
        wrapper.eq("session_id", param.getId());
        wrapper.orderByDesc("id");
        Page<ImMessage> page = new Page<>(param.getPageNum(), param.getPageSize());
        page = messageService.page(page, wrapper);

        // 清空未读数， 更新lastAck
        Long maxMessageId = messageService.maxMessageId();
        // TODO 已读未读， lastACK  放redis
        userSession.setUnread(0L);
        userSession.setLastAck(maxMessageId);
        imUserSessionService.updateById(userSession);

        return HttpResult.ok(page);
    }

    /**
     * 会话消息已读
     * @param reqReadMsgParam
     * @return
     */
    @PostMapping("/msg/read")
    @Transactional
    public HttpResult<String> markRead(@RequestBody ReqReadMsgParam reqReadMsgParam) {
        // 消息已读
        ImUser loginUser = getLoginUser();
//        imUserSessionService.markRead(reqReadMsgParam, loginUser.getId());

        ImMessage one = messageService.getById(reqReadMsgParam.getMsgId());

        // 通知客户端回调
        ImMessage message = new ImMessage();
        message.setId(one.getId());
        message.setSessionId(one.getSessionId());
        message.setFromUser(loginUser.getId());
        message.setToUser(one.getFromUser());
        message.setMessageType(ImMessageType.READ);
        message.setSessionType(ImSessionType.SINGLE);
        msgApi.sendMsg(message);

        return HttpResult.ok();

    }


}
